home *** CD-ROM | disk | FTP | other *** search
- /*
- * sgll.c
- *
- * Practical Algorithms for Image Analysis
- *
- * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
- */
-
- /*
- * SGLL
- *
- * construct segm adj list;
- * version employing shortened segment structure; see also: lsgll.c
- *
- * ms, 11/90;
- * ----------
- * bug fixed in ACCEPT_LEVEL 1: ccurSegm->dij = -ccurSegm->dij:
- * sign had been positive, leading to faulty segment ordering in
- * SGL and subtle error in computed area and length!! ms, 2-26-91;
- */
- #include <stdio.h>
- #include <string.h>
- #include <malloc.h>
- #include <math.h>
-
- #include "lldef.h"
- #include "xsgll.h"
-
-
- #undef DEBUG
-
-
- /*
- * compare list entries (segments):
- * key: distance parameter, dij
- *
- */
- int
- cmpSegmdist (oldSegm, newSegm)
- struct Segmtype *oldSegm, *newSegm;
- {
-
- return (SIGN (oldSegm->dij - newSegm->dij));
- }
-
-
- /*
- * scan list, comparing perpendicular distance dij of newSegm <j>
- * with that of those segments already in current segm adj list (SAL);
- * add newSegm to list: if dij<0, addprev. otherwise add;
- * employs matching function, here cmpSegmdist
- * (see also: llsearch() in llist.c )
- */
- Boolean
- cmpdij (newSegm, sign_dij, sall)
- struct Segmtype *newSegm;
- int sign_dij;
- struct linklist *sall;
- {
- Boolean MatchStatus = False;
-
-
- if (sign_dij > 0) { /* scan bwd from tail until newdij <= existdij */
- lltail (sall);
- do {
- if (((*sall->match) (sall->clp->item, newSegm)) <= 0)
- MatchStatus = True;
-
- } while ((MatchStatus != True) && (llprevious (sall) == True));
- }
- else { /* scan fwd from head until newdij > existdij */
- llhead (sall);
- do {
- if (((*sall->match) (sall->clp->item, newSegm)) > 0)
- MatchStatus = True;
-
- } while ((MatchStatus != True) && (llnext (sall) == True));
- }
-
- return (MatchStatus);
- }
-
-
- /*
- * to check value of inv overlap pki of segment <k> in SAL<j> with
- * the reference segment <i>, fetch segm <k>
- */
- struct Segmtype *
- fetch_segm (csall, sgl_ind)
- struct linklist *csall;
- int sgl_ind;
- {
- struct Segmtype *cSegm;
- Boolean MatchStatus = False;
-
- llhead (csall); /* search SAL for segm <sgl_index> */
- /* skip ref segm at top of list */
-
- while ((llnext (csall) == True) && (MatchStatus != True)) {
- cSegm = (struct Segmtype *) csall->clp->item;
- if (cSegm->segm_ind == sgl_ind)
- MatchStatus = True;
- }
-
- if (MatchStatus == True)
- return (cSegm);
- else
- return ((struct Segmtype *) NULL);
- }
-
-
- /*
- * scan SAL and check whether active segments remain;
- * if so, return Active, otherwise set SalStat of the reference
- * segment of the SAL under inspection to InActive and return InActive
- */
- Boolean
- check_sal_stat (ActiveSegm, list)
- Boolean *ActiveSegm;
- struct linklist *list;
- {
- struct Segmtype *cccSegm, *rrrefSegm;
- Boolean SalStat = InActive;
-
- llhead (list);
- rrrefSegm = (struct Segmtype *) list->clp->item; /* ref segm at top */
- do {
- cccSegm = (struct Segmtype *) list->clp->item;
- if (*(ActiveSegm + cccSegm->segm_ind) == Active)
- SalStat = Active;
-
- } while ((llnext (list) == True) && (SalStat == InActive));
- rrrefSegm->SalStat = SalStat;
-
- return (SalStat);
- }
-
-
-
-
- /*
- * expand doubly linked list by adding a segment, maintaining
- * segments in increasing order of dij
- */
- void
- llexpand (Segm, list)
- struct Segmtype *Segm;
- struct linklist *list;
- {
- int s_dij;
-
- llsetmatch (cmpSegmdist, list);
- switch (s_dij = SIGN (Segm->dij)) {
- case -1:
- llhead (list);
- while (cmpdij (Segm, s_dij, list) != True);
- lladdprev ((char *) Segm, list);
- break;
- case 1:
- lltail (list);
- while (cmpdij (Segm, s_dij, list) != True);
- lladd ((char *) Segm, list);
- break;
- case 0:
- printf ("\n...overlap ignored\n");
- break;
- default:
- printf ("\n...unknown SIGN(dij)!\n");
- break;
- }
- }
-
-
- /*
- * construct segment group list
- * return number of SGLs containing more than the reference segment
- */
- int
- construct_sgll (segm, sall, sgll, n_segm, ovlp_thresh)
- struct Segm *segm;
- struct linklist *sall;
- struct linklist *sgll;
- int n_segm;
- double ovlp_thresh;
- {
- int n_sgl;
- struct linklist *csall, *ccsall, *cccsall; /* ptrs to current lists */
- struct linklist *csgll;
- Boolean *ActiveSegm;
-
- struct Segmtype *refSegm, *curSegm;
- struct Segmtype *rrefSegm, *ccurSegm, *cccurSegm;
-
-
- double dij, dji, pij, pji;
- double pki, pkj;
- int i, ref_index;
- int na_segm, naa_segm;
- Boolean SalStat;
-
- /*
- * ActiveSegm is an array to globally track the status of segments
- * as they are being assigned to SGLs; each segment mmay only be
- * be assigned once;
- * Active: segment unassigned
- * InActive: segment assigned
- */
- ActiveSegm = (Boolean *) calloc (n_segm, sizeof (Boolean));
- for (i = 0; i < n_segm; i++)
- *(ActiveSegm + i) = Active;
-
- n_sgl = 0;
- for (i = 0; i < n_segm; i++) {
- csall = (sall + i);
- llhead (csall); /* ref segm of SAL<i> stored at top */
- refSegm = (struct Segmtype *) csall->clp->item;
- ref_index = i;
- na_segm = 0;
-
-
- if (refSegm->SalStat == Active) { /* SAL active? */
- csgll = (sgll + i); /* set current SGL */
- llinit ((char *) refSegm, csgll); /* init. SGL<i> with ref segm */
-
- ActiveSegm[refSegm->segm_ind] = InActive;
- printf ("\n...SGL<%d> initialized\n", i);
-
- /*
- * scan SAL<i>, the SAL of the reference segment:
- * inspect all active segments <j != i> in the SAL; if pji passes
- * OVLP_THRESH, add <j> to SGL<i> in the order of increasing dij;
- * when reaching the first segm in SAL<i> for which pji<OVLP_THRESH,
- * stop scanning (pji for all followin segments will be smaller!!) and
- * set na_segm != 0 to signal end of scan;
- * in SGL<i> segments with dij<0 will precede the reference element,
- * those with dij>0 will follow it
- */
-
- while ((llnext (csall) == True) && (na_segm == 0)) {
- curSegm = (struct Segmtype *) csall->clp->item;
- if (ActiveSegm[curSegm->segm_ind] == Active) {
- if (curSegm->pji > ovlp_thresh) {
- llexpand (curSegm, csgll);
- ActiveSegm[curSegm->segm_ind] = InActive;
- }
- else
- na_segm++; /* segm remains active */
- }
- } /* reached end of cur SAL */
- if (csgll->listlength > 1)
- n_sgl++; /* count SGLs with more than 1 segm */
-
- if (na_segm == 0) /* no active segm remaining in SAL<i> */
- refSegm->SalStat = InActive;
-
- /*
- * expand SGL<i> if ACCEPT_LEVEL > 0 is indicated:
- * scan SGL<i>, the segm group list just constructed (segments added to
- * SGL<i> at that level are considered to satisfy ACCEPT_LEVEL 0);
- * inspect all active SALs of segments <j> present in SGL<i> (excluding
- * SAL<i> which has just been examined); in each SAL<j>, inspect active
- * elements <k> and compare inverse overlap with OVLP_THRESH:
- * if pki>OVLP_THRESH: add <k> to SGL<i>
- * if ACCEPT_LEVEL == 2:
- * if pji>OVLP_THRESH: add <k> to SGL<i>
- */
- if (ACCEPT_LEVEL > 0) {
- llhead (csgll); /* scan SGL<i>, inspecting SAL<j> */
- do {
- curSegm = (struct Segmtype *) csgll->clp->item;
- if (curSegm->segm_ind != ref_index) { /* skip SAL<i> */
- ccsall = &sall[curSegm->segm_ind]; /* fetch SAL<j> */
- llhead (ccsall); /* ref segm stored at top of SAL */
- rrefSegm = (struct Segmtype *) ccsall->clp->item;
- naa_segm = 0;
-
- if (rrefSegm->SalStat == Active) { /*scan SAL if actv */
- while (llnext (ccsall) == True) {
- ccurSegm = (struct Segmtype *) ccsall->clp->item;
- if (ActiveSegm[ccurSegm->segm_ind] == Active) {
- cccsall = &sall[ccurSegm->segm_ind]; /* SAL<k> */
- cccurSegm = fetch_segm (cccsall, ref_index);
-
- if (cccurSegm != (struct Segmtype *) NULL)
- pki = (double) cccurSegm->pij;
- else {
- pki = -1.0;
- }
-
- /* test inverse overlap */
- /* add segm to SGL if indicated */
- /* ACCEPT_LEVEL 1 */
- if (pki > ovlp_thresh) {
- ccurSegm->dij = -cccurSegm->dij;
- ccurSegm->pij = cccurSegm->pji;
- ccurSegm->pji = (float) pki;
- ccurSegm->sgl_level = 1;
-
- llexpand (ccurSegm, csgll);
-
- ActiveSegm[ccurSegm->segm_ind] = InActive;
-
- llhead (csgll); /* scan SGL from top */
- }
- else if (ACCEPT_LEVEL > 1) {
- cccurSegm = fetch_segm (cccsall, curSegm->segm_ind);
-
- if (cccurSegm != (struct Segmtype *) NULL) {
- pkj = (double) cccurSegm->pij;
- }
- else {
- pkj = -1.0;
- }
-
- /* must reevaluate dij, pij, pji */
- /* with respect to ref segment <i>!! */
- /* ACCEPT_LEVEL 2 */
- if (pkj > ovlp_thresh) {
- prlpar ((segm + ccurSegm->segm_ind)->ptO,
- (segm + ccurSegm->segm_ind)->ptF,
- (segm + refSegm->segm_ind)->ptO,
- (segm + refSegm->segm_ind)->ptF,
- &dij, &dji, &pij, &pji);
- #ifdef DEBUG
- printf ("\n...returned from prlpar():\n");
- printf (" overlap(%d,%d)=%.2lf\n",
- ccurSegm->segm_ind,
- refSegm->segm_ind, pij);
- printf (" overlap(%d,%d)=%.2lf\n",
- refSegm->segm_ind,
- ccurSegm->segm_ind, pji);
- printf (" perp.dist(%d,%d)=%.2lf\n",
- ccurSegm->segm_ind,
- refSegm->segm_ind, dji);
- #endif
- ccurSegm->dij = (float) dji;
- ccurSegm->pij = (float) pij;
- ccurSegm->pji = (float) pji;
- ccurSegm->sgl_level = 2;
-
- llexpand (ccurSegm, csgll);
-
- ActiveSegm[ccurSegm->segm_ind] = InActive;
-
- /* pro-active check of SAL status: */
- /* scan SAL<k> to see if actv segm remain */
- /* if not, mark SAL<k> InActive */
- SalStat = check_sal_stat (ActiveSegm, cccsall);
-
- llhead (csgll); /* scan SGL from top */
- }
- }
- else
- naa_segm++; /* segm remains active */
- }
- } /* reached end of cur SAL */
- if (naa_segm == 0) /* no actv segm remain in SAL */
- rrefSegm->SalStat = InActive;
- }
- }
- } while (llnext (csgll) == True); /* end of SGL<i> */
- }
- }
- }
- free (ActiveSegm);
-
- return (n_sgl);
- }
-